package com.demo.test.utils;

import org.nd4j.autodiff.samediff.SDVariable;
import org.nd4j.autodiff.samediff.SameDiff;
import org.nd4j.linalg.activations.IActivation;
import org.nd4j.linalg.activations.impl.*;

public enum Activation {
    //这是一个用于处理稀疏数据的激活函数，它通过将输入值映射到立方体函数上来工作。
    CUBE,
    //Exponential Linear Unit 是 ELU 的缩写，它是一种用于神经网络的激活函数。
    ELU,
    //这是一个非线性函数，它通过将输入值映射到 -1 和 1 之间来工作。
    HARDSIGMOID,
    //这是双曲正切函数的限制版本，它将输入值映射到 -1 到 1 的范围内。
    HARDTANH,
    //这可能表示一个不进行任何转换的函数，或者它可能是一个线性函数，即 y = x。
    IDENTITY,
    //这是一个修改版的 ReLU，它在负输入值处有一个小的正向输出，以防止在训练过程中出现“死亡”神经元。
    LEAKYRELU,
    //这可能是一种有理双曲正切函数，它试图在保持计算效率的同时实现双曲正切的非线性性。
    RATIONALTANH,
    //ReLU（Rectified Linear Unit）是一种非常常见的神经网络激活函数，它在输入值小于 0 时输出 0，而在输入值大于或等于 0 时输出该输入值
    RELU,
    //这是 ReLU 的变体，将输出限制在 0 到 6 的范围内。
    RELU6,
    //Randomized ReLU 是 ReLU 的一个变体，其中负输入值被随机化的一个小正值替换，以防止“死亡”神经元。
    RRELU,
    //Sigmoid 函数将输入值映射到 0 到 1 的范围内，经常用于二元分类问题。
    SIGMOID,
    //这个函数将输入值映射到概率分布上，通常用于多分类问题。
    SOFTMAX,
    //这个函数类似于 ReLU，但是它在输入值大于 0 时有一个更平滑的斜率。
    SOFTPLUS,
    //这个函数类似于 HARDTANH，但是它在输入值接近于 0 时有一个更平滑的斜率。
    SOFTSIGN,
    //双曲正切函数将输入值映射到 -1 到 1 的范围内。
    TANH,
    //这可能是一种修正版的双曲正切函数，其行为类似于 ReLU。
    RECTIFIEDTANH,
    //SELU（Scaled Exponential Linear Unit）是一种自归一化的激活函数。
    SELU,
    //Swish 是一种神经网络激活函数和自归一化方法，它是 ReLU 和sigmoid函数的混合体。
    SWISH,
    //这是一种具有阈值的 ReLU 激活函数。
    THRESHOLDEDRELU,
    //GELU（Gaussian Error Linear Unit）是一种新的神经网络激活函数，它使用高斯分布来建模神经元的错误输出分布。
    GELU,
    //Mish 是一种新的神经网络激活函数，它使用指数函数和 softplus 函数的组合来实现比 ReLU 更平滑的斜率。
    MISH;

    private Activation() {
    }

    public IActivation getActivationFunction() {
        switch(this) {
            case CUBE:
                return new ActivationCube();
            case ELU:
                return new ActivationELU();
            case HARDSIGMOID:
                return new ActivationHardSigmoid();
            case HARDTANH:
                return new ActivationHardTanH();
            case IDENTITY:
                return new ActivationIdentity();
            case LEAKYRELU:
                return new ActivationLReLU();
            case RATIONALTANH:
                return new ActivationRationalTanh();
            case RECTIFIEDTANH:
                return new ActivationRectifiedTanh();
            case RELU:
                return new ActivationReLU();
            case RELU6:
                return new ActivationReLU6();
            case SELU:
                return new ActivationSELU();
            case SWISH:
                return new ActivationSwish();
            case RRELU:
                return new ActivationRReLU();
            case SIGMOID:
                return new ActivationSigmoid();
            case SOFTMAX:
                return new ActivationSoftmax();
            case SOFTPLUS:
                return new ActivationSoftPlus();
            case SOFTSIGN:
                return new ActivationSoftSign();
            case TANH:
                return new ActivationTanH();
            case THRESHOLDEDRELU:
                return new ActivationThresholdedReLU();
            case GELU:
                return new ActivationGELU();
            case MISH:
                return new ActivationMish();
            default:
                throw new UnsupportedOperationException("Unknown or not supported activation function: " + this);
        }
    }

    public static Activation fromString(String name) {
        return valueOf(name.toUpperCase());
    }

    public SDVariable asSameDiff(SameDiff sd, SDVariable input) {
        return this.asSameDiff((String)null, sd, input);
    }

    public SDVariable asSameDiff(String variableName, SameDiff sd, SDVariable input) {
        switch(this) {
            case CUBE:
                return sd.math().pow(variableName, input, 3.0D);
            case ELU:
                return sd.nn().elu(variableName, input);
            case HARDSIGMOID:
            case RATIONALTANH:
            case RECTIFIEDTANH:
            case RELU6:
            case SELU:
            case SWISH:
            case RRELU:
            case THRESHOLDEDRELU:
            default:
                throw new UnsupportedOperationException("Activation function not yet supported: " + this);
            case HARDTANH:
                return sd.nn().hardTanh(variableName, input);
            case IDENTITY:
                return sd.identity(variableName, input);
            case LEAKYRELU:
                return sd.nn().leakyRelu(variableName, input, 0.0D);
            case RELU:
                return sd.nn().relu(variableName, input, 0.0D);
            case SIGMOID:
                return sd.nn().sigmoid(variableName, input);
            case SOFTMAX:
                return sd.nn().softmax(variableName, input);
            case SOFTPLUS:
                return sd.nn().softplus(variableName, input);
            case SOFTSIGN:
                return sd.nn().softsign(variableName, input);
            case TANH:
                return sd.math().tanh(variableName, input);
            case GELU:
                return sd.nn().gelu(variableName, input);
        }
    }
}
